#include "pager.h"
#include "table.h"
#include <assert.h>
#include <stdlib.h>   // 包含EXIT_FAILURE的定义
#include <fcntl.h>    // 包含O_CREAT的定义
#include <sys/stat.h> // 包含S_IWUSR的定义

Pager *pager_open(const char *filename)
{
    int fd = open(filename,
                  O_RDWR |      // read write mode
                      O_CREAT,  // create file if not exists
                  S_IWUSR |     // user write permission
                      S_IRUSR); // user read permission
    if (fd < 0)
    {
        printf("Can't open or create file %s\n", filename);
        exit(EXIT_FAILURE);
    }
    FILE *file = fdopen(fd, "w+");
    Pager *pager = malloc(sizeof(Pager));
    pager->file_descriptor = file;
    // 获取文件大小
    struct stat sb = {0};
    fstat(fd, &sb);
    pager->file_length = sb.st_size;
    pager->num_pages=(pager->file_length/PAGE_SIZE);
    if(pager->file_length%PAGE_SIZE!=0){
        printf("Db file is not a whole number of pages. Corrupt file.\n");
        exit(EXIT_FAILURE);
    }
    // 初始化pager的pages
    for (uint32_t i = 0; i < TABLE_MAX_PAGES; i++)
    {
        pager->pages[i] = NULL;
    }
    return pager;
};

// 获取第几页page的指针
void *get_page(Pager *pager, uint32_t page_num)
{
    assert(pager != NULL);
    if (page_num > TABLE_MAX_PAGES)
    {
        printf("Tried to fetch page number out of bounds. %d > %d\n", page_num, TABLE_MAX_PAGES);
        exit(EXIT_FAILURE);
    }
    if (pager->pages[page_num] == NULL)
    {
        void *page = malloc(PAGE_SIZE);
        // 缺页了，要从文件里读取
        fseek(pager->file_descriptor, page_num * PAGE_SIZE, SEEK_SET);
        int bytes_read = fread(page, PAGE_SIZE, 1, pager->file_descriptor);
        if (bytes_read < 0)
        {
            printf("can't read page num :%d\n", page_num);
            exit(EXIT_FAILURE);
        }
        if (page_num >= pager->num_pages)
        {
            pager->num_pages = page_num + 1;
            
        }
        pager->pages[page_num] = page;
    }
    return pager->pages[page_num];
};

// 将pager的第page_num保存起来，写入文件
void pager_flush(Pager *pager, uint32_t page_num)
{
    // size是行数
    off_t offset = fseek(pager->file_descriptor, page_num * PAGE_SIZE, SEEK_SET);
    //一次性写入ROW_SIZE 总共大小为PAGE_SIZE
    int bytes_written = fwrite(pager->pages[page_num], PAGE_SIZE, 1, pager->file_descriptor);
    if (bytes_written < 0)
    {
        printf("can't write page num :%d\n", page_num);
        exit(EXIT_FAILURE);
    }
};

//获取pager的第一个未使用的page
uint32_t get_unused_page_num(Pager* pager){
    return pager->num_pages;
};